package com.powernode.config.filter;

import com.alibaba.fastjson2.JSONObject;
import com.powernode.constant.AuthConstants;
import com.powernode.model.CodeEnum;
import com.powernode.model.R;
import com.powernode.model.SecurityUser;
import com.powernode.util.JWTUtils;
import com.powernode.util.ResponseUtils;
import com.powernode.util.TokenManager;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * token转换过滤器
 */
@Component
public class TokenFilter extends OncePerRequestFilter {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private TokenManager tokenManager;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 从请求头中获取Authorization的值
        String authorizationValue = request.getHeader(AuthConstants.AUTHORIZATION);
        // 判断是否存在
        if (!StringUtils.hasText(authorizationValue)) {
            ResponseUtils.write(response, R.FAIL(CodeEnum.TOKEN_EMPTY));
            return;
        }
        // 判断Authorization值是否以Bearer开头
        if (!authorizationValue.startsWith(AuthConstants.BEARER)) {
            ResponseUtils.write(response, R.FAIL(CodeEnum.TOKEN_INVALIDATE));
            return;
        }
        // 从Authorization值中获取令牌TOKEN
        String jwt_token = authorizationValue.replaceFirst(AuthConstants.BEARER, "");
        // 判断是否有值
        if (!StringUtils.hasText(authorizationValue)) {
            ResponseUtils.write(response, R.FAIL(CodeEnum.TOKEN_EMPTY));
            return;
        }
        // 验证令牌TOKEN
        if (!JWTUtils.verifyJwt(jwt_token)) {
            ResponseUtils.write(response, R.FAIL(CodeEnum.TOKEN_INVALIDATE));
            return;
        }
        // 判断redis中是否存在令牌TOKEN
        if (!stringRedisTemplate.hasKey(AuthConstants.TOKEN_REDIS_KEY_PREFIX + jwt_token)) {
            ResponseUtils.write(response, R.FAIL(CodeEnum.TOKEN_INVALIDATE));
            return;
        }
        // 获取“记住我”状态
        Boolean rememberMe = Boolean.parseBoolean(request.getHeader(AuthConstants.REMEMBER_ME));
        // token续约
        tokenManager.flushTokenTime(jwt_token,rememberMe);

        // 解析令牌TOKEN
        String securityUserJsonStr = JWTUtils.parseJwt(jwt_token);
        // 将SecurityUser的json格式字符串转换为对象
        SecurityUser securityUser = JSONObject.parseObject(securityUserJsonStr, SecurityUser.class);
        // 获取用户权限信息
        Set<SimpleGrantedAuthority> authorities = securityUser.getPermissionList().stream().map(SimpleGrantedAuthority::new).collect(Collectors.toSet());
        // 创建认证信息
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(securityUser, null, authorities);
        // 将认证信息存放到Security上下文中
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        // 放行
        filterChain.doFilter(request, response);
    }
}
